package cool.mylog.mylog2end.controller;

import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Policy;
import com.tencent.cloud.Response;
import com.tencent.cloud.Statement;
import com.tencent.cloud.cos.util.Jackson;
import cool.mylog.mylog2end.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import java.util.TreeMap;

/**
 * cos
 * 腾讯云临时获取密钥，权限控制
 */
@RestController
@RequestMapping("cos")
public class COSController {

    @Value("${tencent-cloud.cos.secretId}")
    private String secretId;

    @Value("${tencent-cloud.cos.secretKey}")
    private String secretKey;

    @Value("${tencent-cloud.cos.bucket}")
    private String bucket;

    @Value("${tencent-cloud.cos.region}")
    private String region;

    @Value("${tencent-cloud.cos.durationSeconds}")
    private Integer durationSeconds;

    /**
     * 获取临时密钥配置：
     * 1800秒
     *
     * @return 临时密钥配置
     */
    private TreeMap<String, Object> getConfig() {
        TreeMap<String, Object> config = new TreeMap<String, Object>();
        config.put("secretId", secretId);
        config.put("secretKey", secretKey);
        config.put("bucket", bucket);
        config.put("region", region);
        config.put("durationSeconds", durationSeconds); // 临时密钥有效时长，单位是秒
        return config;
    }

    /**
     * get_credential 获取临时密钥
     *
     * @return 临时密钥 tmpSecretId、tmpSecretKey、sessionToken
     */
    @GetMapping("get_credential")
    public Response getCredential(String token) {
        Long id = JwtUtils.getId(token);
        if (id == 0) return null;

        TreeMap<String, Object> config = getConfig();

        // 指定访问前缀
        config.put("allowPrefixes", new String[]{
                "users/" + id + "/*",
        });

        // 密钥的权限列表。简单上传和分片需要以下的权限
        config.put("allowActions", new String[]{
                "name/cos:*",
                // "name/cos:List*",
                // "name/cos:Get*",
                // "name/cos:Head*",
                // "name/cos:OptionsObject",
                //
                // "name/cos:PutObject", //简单上传操作
                // "name/cos:PostObject", //表单上传对象、小程序上传
                // "name/cos:GetBucket", //获取对象
                // "name/cos:HeadBucket", //检索存储桶及其权限
                // "name/cos:DeleteBucket", //删除对象
                // // 分块上传
                // "name/cos:InitiateMultipartUpload", // 初始化分块操作
                // "name/cos:ListMultipartUploads", // List 进行中的分块上传
                // "name/cos:ListParts", // List 已上传分块操作
                // "name/cos:UploadPart", // 上传分块操作
                // "name/cos:CompleteMultipartUpload", // 完成所有分块上传操作
                // "name/cos:AbortMultipartUpload", // 取消分块上传操作
        });

        // Statement statement = new Statement();
        // statement.setEffect("allow"); // 声明设置的结果是允许操作
        /**
         * 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
         * 权限列表请参见 https://cloud.tencent.com/document/product/436/31923
         * 规则为 {project}:{interfaceName}
         * project : 产品缩写  cos相关授权为值为cos,数据万象(数据处理)相关授权值为ci
         * 授权所有接口用*表示，例如 cos:*,ci:*
         * 添加一批操作权限 :
         */
        // statement.addActions(new String[]{
        //         "cos:PutObject",
        //         // 表单上传、小程序上传
        //         "cos:PostObject",
        //         // 分块上传
        //         "cos:InitiateMultipartUpload",
        //         "cos:ListMultipartUploads",
        //         "cos:ListParts",
        //         "cos:UploadPart",
        //         "cos:CompleteMultipartUpload",
        //         // 处理相关接口一般为数据万象产品 权限中以ci开头
        //         // 创建媒体处理任务
        //         "ci:CreateMediaJobs",
        //         // 文件压缩
        //         "ci:CreateFileProcessJobs"
        // });

        /**
         * 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径
         * 资源表达式规则分对象存储(cos)和数据万象(ci)两种
         * 数据处理、审核相关接口需要授予ci资源权限
         *  cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path}
         *  ci  : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path}
         * 列举几种典型的{path}授权场景：
         * 1、允许访问所有对象："*"
         * 2、允许访问指定的对象："a/a1.txt", "b/b1.txt"
         * 3、允许访问指定前缀的对象："a*", "a/*", "b/*"
         *  如果填写了“*”，将允许用户访问所有资源；除非业务需要，否则请按照最小权限原则授予用户相应的访问权限范围。
         *
         * 示例：授权examplebucket-1250000000 bucket目录下的所有资源给cos和ci 授权两条Resource
         */
        // statement.addResources(new String[]{
        //         "*",
        //         // "qcs::cos:ap-chongqing:uid/1250000000:examplebucket-1250000000/*",
        //         // "qcs::ci:ap-chongqing:uid/1250000000:bucket/examplebucket-1250000000/*"
        // });

        // 把一条 statement 添加到 policy，可以添加多条
        // Policy policy = new Policy();
        // policy.addStatement(statement);
        // // 将 Policy 示例转化成 String，可以使用任何 json 转化方式，这里是本 SDK 自带的推荐方式
        // config.put("policy", Jackson.toJsonPrettyString(policy));

        try {
//            return null;
            return CosStsClient.getCredential(config);
        } catch (Exception e) {
            // e.printStackTrace();
            throw new IllegalArgumentException("no valid secret !");
        }
    }
}
